package io.gitee.twoke.generator.engine.impl.metadata.impl;

import io.gitee.twoke.generator.engine.impl.AbstractQuery;
import io.gitee.twoke.generator.engine.impl.Page;
import io.gitee.twoke.generator.engine.impl.interceptor.CommandContext;
import io.gitee.twoke.generator.engine.impl.interceptor.CommandExecutor;
import io.gitee.twoke.generator.engine.impl.metadata.TableColumn;
import io.gitee.twoke.generator.engine.impl.metadata.TableColumnQuery;
import cn.hutool.core.util.StrUtil;

import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

public class TableColumnQueryImpl  extends AbstractQuery<TableColumnQuery, TableColumn> implements TableColumnQuery {

    private String tableName;

    public TableColumnQueryImpl() {
    }

    public TableColumnQueryImpl(CommandExecutor commandExecutor) {
        super(commandExecutor);
    }

    public TableColumnQueryImpl(CommandContext commandContext) {
        super(commandContext);
    }

    @Override
    public long executeCount(CommandContext commandContext) {
        return executeList(commandContext, null).size();
    }

    @Override
    public List<TableColumn> executeList(CommandContext commandContext, Page page) {
        if (StrUtil.isBlank(tableName)) {
            throw new IllegalArgumentException("tableName is null or empty");
        }
        List<TableColumn> columns = null;
        try {
            Connection connection = commandContext.getDbSqlSession().getSqlSession().getConnection();
            DatabaseMetaData metaData = connection.getMetaData();
            ResultSet rs = metaData.getColumns(connection.getCatalog(), connection.getSchema(), tableName, null);
            columns = new ArrayList<>();

            while (rs.next()) {
                columns.add(TableColumImpl.builder()
                        .name(rs.getString("COLUMN_NAME"))
                        .comment(rs.getString("REMARKS"))
                        .dataType(rs.getInt("DATA_TYPE"))
                        .defaultValue(rs.getString("COLUMN_DEF"))
                        .isRequired(rs.getString("IS_NULLABLE").equals("NO"))
                        .build());
            }
            Map<String, TableColumn> columnDataMap = columns.stream().collect(Collectors.toMap(TableColumn::getName, column -> column));
            ResultSet primaryKeys = metaData.getPrimaryKeys(connection.getCatalog(), connection.getSchema(), tableName);
            while (primaryKeys.next()) {
                ((TableColumImpl)columnDataMap.get(primaryKeys.getString("COLUMN_NAME"))).setPrimaryKey(true);
            }
        } catch (SQLException e){
            e.printStackTrace();
        }
        return Optional.ofNullable(columns).orElse(new ArrayList<>());
    }

    @Override
    public TableColumnQuery tableName(String tableName) {
        if (StrUtil.isBlank(tableName)) {
            throw new IllegalArgumentException("tableName is null or empty");
        }
        this.tableName = tableName;
        return this;
    }
}
